STELLA - A Lisp-like Language for Symbolic Programming with Delivery in Common Lisp, C++, and Java
نویسندگان
چکیده
We describe STELLA,1 a strongly typed, object-oriented, Lisp-like language, designed to facilitate symbolic programming tasks in artificial intelligence applications. STELLA preserves those features of Common Lisp deemed essential for symbolic programming such as built-in support for dynamic data structures, heterogeneous collections, firstclass symbols, powerful iteration constructs, name spaces, an object-oriented type system with a meta-object protocol, exception handling, and language extensibility through macros, but without compromising execution speed, interoperability with non-STELLA programs, and platform independence. STELLA programs are translated into a target language such as C++, Common Lisp, or Java, and then compiled with the native target language compiler to generate executable code. The language constructs of STELLA are restricted to those that can be translated directly into native constructs of the intended target languages, thus enabling the generation of highly efficient as well as readable code. Introduction From its inception about 40 years ago, Lisp was intended specifically to support the writing of artificial intelligence (AI) software (McCarthy 1981), and it has been one of the most popular AI programming languages ever since. However, despite its high level of maturity, for example, the existence of standards for major dialects such as Common Lisp and Scheme and the emergence of an international standard for ISLISP, it has not become a mainstream programming language such as C, C++ or, lately but quickly, Java. This is one of the reasons why it is generally difficult to deliver Lisp libraries or applications that smoothly interoperate with standard non-Lisp software, such as, for example, GUI tools, commercial offthe-shelf software, tool libraries, etc. Other reasons are the technical nature and size of Lisp implementations (in particular for feature-rich dialects such as Common Lisp), as well as the lack of Lisp knowledge in the general nonAI programming community. Balzer (1990) conjectures that AI’s lack of impact on real world software engineering is due to its isolationist technology and approaches manifested by its use of idiosyncratic languages (Lisp), 1 “STELLA” is an acronym for Strongly TypEd Lisp-like LAnguage. idiosyncratic environments, and idiosyncratic hardware (now extinct Lisp machines). From the standpoint of AI this is very unfortunate, since, on the one hand, Lisp is extremely well suited for symbolic programming tasks commonly found in AI. For example, Shrobe (1996) argues that the AI community still needs Lisp because of its dynamic nature and rich development environments that facilitate rapid prototyping, as well as for its unique support for creating and embedding new domain or problem-specific languages. On the other hand, the success of AI as perceived outside of the field is more and more linked to the successful fielding of AI technology in non-AI settings, and, since this success depends heavily on the technical and commercial viability of the programming languages used, we claim that Lisp is an increasingly less suitable choice. When the second author embarked on the project of developing a large knowledge representation system that had to be delivered in C++, he was faced exactly with the dilemma described above: the symbolic programming nature of the project strongly favored Common Lisp while “real world” constraints demanded C++. The solution was the development of a new language called STELLA, which preserves those features of Common Lisp deemed essential for symbolic programming, but without compromising execution speed, interoperability with non-STELLA programs, and platform independence. The motivation for the development of the language Dylan (Shalit 1996) was very similar, namely, to preserve the best features of Common Lisp without compromising the ability to generate tight and efficient application programs. Scott Fahlman who has been involved in the development of Common Lisp as well as Dylan writes that “if Dylan becomes popular for mainstream applications, it will free AI and expert system programmers from having to choose between life in the Lisp ghetto or the C++ minefield” (Shrobe et al. 1996, p.12). But the question is: will it become popular? We do not venture a bet on the answer to this question. Instead, STELLA takes a safer approach by using a translation scheme that can deliver STELLA programs in three already established and widely accepted languages. Even if STELLA does not become a mainstream language – which is quite likely – it can still deliver on its promise of making AI applications available to the programming mainstream in a way that was not previously possible. An Overview of STELLA STELLA is a strongly typed, object-oriented, Lisp-like language. STELLA programs are first translated into either Common Lisp, C++, or Java, and then compiled with any conventional compiler for the chosen target language to generate executable code. Figure 1 gives an overview of the STELLA system architecture. Over 95% of the STELLA system is written in STELLA itself, which is the reason for the circular arc emanating from the translator. The design of STELLA borrows from a variety of programming languages, most prominently from Common Lisp (Steele 1990), and to a lesser degree from other object-oriented languages such as Eiffel (Meyer 1992), Sather (Stoutamire & Omohundro 1996), and Dylan (Shalit 1996). Since STELLA has to be translatable into C++ (Stroustrup 1991) and Java (Gosling, Joy, & Steele 1996), various restrictions of these languages also influenced its design. In the following, we assume that the reader is familiar with basic Common Lisp concepts, and has at least some familiarity with C++ or Java. Let us start with a cursory overview of STELLA’s main features: Syntax: STELLA uses a parenthesized, uniform expression syntax similar to Lisp. Most definitional constructs and control structures are similar to their Common Lisp analogues with variations to support types. Type system: STELLA is strongly typed and supports efficient static compilation similar to C++. Types are required for the arguments and return values of functions and methods, for global variables, and for slot definitions. Local, lexically scoped variables can be typed implicitly by relying on type inference. Object system: Types are organized into a single inheritance class hierarchy. Restricted multiple inheritance is allowed via mixin classes. Dynamic method dispatch is based on the runtime type of the first argument (similar to C++ and Java). Slots can be static (native) or dynamic. Dynamic slots can be defined at runtime and do not occupy any space until they are filled. Slots can have both initial and default values, and demons can be triggered by slot accesses. A meta-object protocol allows the control of object creation, initialization, termination, and destruction. Control structure: Functions and methods are distinguished. They can have multiple (zero or more) return values and a variable number of arguments. Lispstyle macros are supported to facilitate syntax extensions. Expressions and statements are distinguished. Local variables are lexically scoped, but dynamically scoped variables (specials) are also supported. STELLA has an elegant, uniform, and efficient iteration mechanism plus a built-in protocol for iterators. An exception mechanism can be used for error handling and non-local exits. Symbolic programming: Symbols are first-class objects, and extensive support for dynamic datatypes such as constrees, lists, sets, association lists, hash tables, extensible vectors, etc., is available. A backquote mechanism facilitates macro writing and code generation. Interpreted function call, method call, slot access, and object creation is supported, and a restricted evaluator is also available. Name spaces: Functions, methods, variables, and classes occupy separate name spaces (i.e., the same name can be used for a function and a class). A hierarchical module system compartmentalizes symbol tables and supports large-scale programming. Memory management: STELLA relies on automatic memory management via a garbage collector. For Lisp and Java the native garbage collector is used. For the C++ version of STELLA we use the Boehm-Weiser conservative garbage collector (Boehm 1993) with good results. Various built-in support for explicit memory management is also available. The Common Lisp features most prominently absent from STELLA are anonymous functions via lambda abstraction, lexical closures, multi-methods, full-fledged eval (a restricted evaluator is available), optional and keyword arguments, and a modifiable readtable. STELLA does also not allow dynamic re/definition of functions and classes, even though the Lisp-based development environment provides this facility (similar to Dylan). The main influences of C++ and Java onto STELLA are the strong typing, limited multiple inheritance, first-argument polymorphism, and the distinction between statements and expressions. Translation Instead of Compilation Maybe the most important characteristic of STELLA that distinguishes it from other approaches to the problem of Lisp-based application generation and interoperability is its translation philosophy. One of the main design goals has been to allow a direct translation into readable, conventional, and efficient code of the various target Figure 1: STELLA system architecture languages that can be compiled with conventional compilers, since that achieves the highest degree of platform independence and interoperability with nonSTELLA programs without sacrificing efficiency. Readability is of primary concern, since it enables a STELLA-illiterate application programmer to effectively and efficiently integrate some mainstream application with a piece of AI technology written in STELLA. Conventional Lisp-to-C translators are an inferior alternative, since they use C more like an assembly language which makes it difficult to access and understand underlying data and control structures. Integration approaches based on foreign function interfaces or protocols such as CORBA sacrifice efficiency, since they require data conversions or various layers of protocol. When a STELLA program is translated into Common Lisp, C++, or Java, classes are mapped onto classes, slots onto slots, methods onto methods, functions onto functions (or static methods), etc. Native datatypes are used whenever possible, for example, STELLA strings become Lisp or C++ strings, integers are mapped onto integers, etc. This is illustrated by Figure 2 which shows a very simple STELLA function and its translations into Common Lisp and C++. Both translations are very direct and straightforward. In the Common Lisp translation all functions used from the Lisp package are qualified with the CL package prefix. Note, that for Lisp all type information is dropped (at higher optimization levels some type information is retained – sacrificing some readability to provide optimization hints to the Lisp compiler). The C++ translation is even more similar to the original STELLA code (the C++ pretty-printing in this and all following examples has been changed slightly to save vertical space). Note, that both the return value and the parameter of the STELLA function are explicitly typed. Since STELLA distinguishes between statements and expressions (similar to C++), the STELLA if does not return a value; hence, function values are returned via explicit calls to return. The direct mapping between STELLA and the target languages not only serves readability but also efficiency. For example, in the C++ translation function calls do not require an extra indirection through a function cell, method calls use the very efficient C++ v-table mechanism, and slot access is almost as efficient as the access to local variables. These are all areas where the expressiveness and dynamic nature of Common Lisp has to be paid for with a loss of efficiency. The STELLA Type System The most fundamental difference between STELLA and Common Lisp is that STELLA is strongly typed. While Common Lisp does have a full-fledged and complex type system, type declarations for functions and variables are completely optional. Moreover, a Common Lisp compiler is free to ignore any user provided type declarations, which discourages programmers to provide them in the first place (if they are not discouraged already by the somewhat arcane declaration syntax). Most Lisp programmers regard the untyped nature of Common Lisp as a feature that facilitates rapid prototyping and only provide type information if they hope for a particular optimization by the compiler. Since STELLA is aimed to be directly translatable into strongly-typed languages such as C++ or Java, it has to have a type system that can be mapped more or less directly onto the type systems of these target languages. Strong typing might seem unpalatable to many Lisp programmers accustomed to a programming style that does not rely on explicit typing; however, we will show that STELLA’s sophisticated type system combined with its type inference mechanism allows one to get away with a minimum of explicit type declarations while still reaping the safety and performance benefits of a strongly typed language. Types in STELLA can be categorized into literal types such as INTEGER or STRING, and object (or nonliteral) types such as OBJECT, LIST, or SYMBOL. This corresponds roughly to the distinction between primitive and reference types in Java. In the simplest case, a type corresponds to a class. For example, the following class definition creates the type PERSON: By convention, we upcase type names, even though this usually does not matter, since by default STELLA is caseinsensitive. The class definition shown above uses a nested keyword/value syntax similar to the defclass macro of the Common Lisp Object System (CLOS), but with a different set of option keywords. It defines the new class (or type) PERSON as a subclass of the class OBJECT. In fact, OBJECT is the top of the STELLA ! " # $ $ % &
منابع مشابه
Importing the Gnu Multiple Precision Package (GMP) into Lisp, and implications for Functional Programming
Advocating the use of a Common Lisp as a central organizing environment for building scientific computing systems runs counter to the conventional wisdom, which suggests that languages like Fortran, C++, or even Java, are more suitable. We prefer Lisp based on its debugging features, interactivity, memory model, existing code-base for computer algebra and user interfaces, and for purposes of th...
متن کاملRemote Access to a Symbolic Computation System for Algebraic Topology: A Client-Server Approach
Kenzo is a Symbolic Computation system created by Sergeraert for computing in Algebraic Topology. It is programmed in Common Lisp and this programming language also acts as user interface. In this paper, a prototype to provide remote access for Kenzo is presented. This has been accomplished by using Corba technology: clients have been developed both in Java and Common Lisp (the server is always...
متن کاملDynamic reconfiguration with CORBA and Common Lisp: A position paper
In languages such as C, C++, and Java such modifications can entail recompiling the IDL, recompiling the application, restarting all of the processes that interact, and restoring the state of the system to the situation of interest; this is true in many cases for Java applications as well. This process results in a slower development cycle than would be the case if the server could be modified ...
متن کاملMixing Lisps in Kawa
Kawa started as a Scheme implementation written in Java, based on compiling Scheme forms to Java byte-codes. It has developed into a powerful Scheme dialect whose strengths include speed and easy access to Java classes. It is Free Software that some companies depend on. The Kawa compiler and run-time environment have been generalized to implement other languages besides Scheme, both in the Lisp...
متن کاملVisual Lisp/CLOS programming in OpenMusic
OpenMusic (OM) is a visual programming language developed on top of Common Lisp and CLOS, in which most of the functional and object-oriented programming concepts can be implemented and carried out graphically. Although this visual language was designed for musical applications, the focus in this paper is to describe and study OM as a complete general-purpose programming environment.
متن کامل